home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_ai / ai8805 / eq_out.ari next >
Encoding:
Text File  |  1988-03-25  |  8.3 KB  |  228 lines

  1. %------------ start of eq_out.ari --------------------------------------
  2. %
  3. %
  4. %
  5. %
  6. /* This module removes equalities from rule bodies and replaces them with
  7.    patterns.  As an example, the rule
  8.  
  9.         prdbms_goal(X) :-
  10.               book( Authors, Title, Price, Publisher,  Topic, Date),
  11.               publisher(Name, Address),
  12.               Publisher = Address,
  13.               Topic = prolog,
  14.               X =[ Authors, Title, Publisher, Address ]),
  15.  
  16.    is changed to
  17.  
  18.        prdbms_goal([_00CD,_00D1,_00D9,_00D9]) :-
  19.                book(_00CD,_00D1,_00D5,_00D9,prolog,_00E1) ,
  20.                publisher(_00F5,_00D9).
  21.  
  22.  Author:  Rodger Knaus
  23.           Instant Recall
  24.           Box 30134
  25.           5900 Walton Rd.
  26.           Bethesda, Md. 20814
  27.           (301) 530-0898
  28.  
  29. Note: trace_message is called for tracing purposes only in this file.
  30.       You can either get trace_message as part of Prolog Tools from
  31.       Instant Recall, or write your own, or use the dummy provided
  32.       below.
  33.  
  34. */
  35.  
  36. trace_message(_):-!.
  37.  
  38. %--------------- eq_out --------------------------------------------------
  39. /* This predicate removes equalities from rule bodies and replaces them with
  40.    patterns.  The first argument is an input rule, possibly containing
  41.    equalities.  The 2nd. argument is an equivalent rule with
  42.    "assignment-statement-like" equality subgoals replaced by patterns.
  43. */
  44.  
  45.  
  46. eq_out( (Head :- Body) , New_clause  ) :-
  47.                % get the list of subgoals in the rule body
  48.     get_rule_body_as_list( Body , Body_subgoal_list),                !,
  49.                % this is just a trace -- you can take it out
  50.     trace_message([$Body_subgoal_list = $,Body_subgoal_list]),       !,
  51.                % carry out unifications that the equalities
  52.                % express, when the left argument is a variable
  53.     eq_out_hlpr( (Head :- Body), Body_subgoal_list),             !,
  54.                % remove those equalities from the list of subgoals
  55.                % -- we have just done them at "compile time"è    remove_equalities( Body_subgoal_list, List_without_equalities),  !,
  56.                % build the output rule
  57.     build_clause( Head ,  List_without_equalities , New_clause).
  58.  
  59. %--------------- eq_out_hlpr ---------------------------------------------
  60. /*
  61. Call:  eq_out_hlpr( In_rule, Body_subgoal_list)
  62.  
  63. Input args:
  64.  
  65.        In_rule = a Prolog goal (may be a rule)
  66.  
  67.        Body_subgoal_list = a list of the subgoals in the body of
  68.                            In_rule
  69.  
  70.  
  71. */
  72.                % nothing to do if the subgoal list is empty.
  73. eq_out_hlpr( In_rule, []) :-
  74.          trace_message([$ e eq_out_hlpr empty set rule$]),
  75.               !.
  76.  
  77.                % if the first subgoal is an assignment-like equality,
  78.                % then call (execute) this unification
  79. eq_out_hlpr( In_rule, [Term | Terms]) :-
  80.          trace_message([$ e eq_out_hlpr assignment  rule$]),
  81.          trace_message([$ Term =$, Term ]),
  82.          trace_message([$ Terms =$, Terms ]),
  83.                % test for an assignment-like equality,
  84.     is_assignment( Term), !,
  85.          trace_message([$ leading term is assignment $]),
  86.                % force the unification expressed by Term
  87.     call(Term),
  88.          trace_message([$ a assignment rule = $,In_rule ]),
  89.                % recurse
  90.     eq_out_hlpr( In_rule, Terms).
  91.  
  92.                % otherwise, just go on to the remaining subgoals
  93. eq_out_hlpr( In_rule, [ _ | Terms]) :-
  94.          trace_message([$ e eq_out_hlpr dflt  rule$]),
  95.          trace_message([$ Terms =$, Terms ]),
  96.                % recurse
  97.     eq_out_hlpr( In_rule, Terms).
  98.  
  99. %--------------- is_assignment -------------------------------------------
  100. /* This predicate recognizes goals that are assignment-like equalities,
  101.    <Variable > = < Term>.  These goals, when executed, unify the
  102.     Variable with the Term.
  103. */
  104.  
  105. is_assignment( =(Var, Term)) :-
  106.      var(Var).
  107.  
  108.  
  109. %--------------- get_rule_body_as_list -----------------------------------è/* This predicate returns a rule Body as a list of subgoals */
  110.  
  111. get_rule_body_as_list( Body, Body_subgoal_list)  :-
  112.               % we do this by using build_conjunction " in reverse "
  113.          build_conjunction( Body_subgoal_list, Body).
  114.  
  115. %--------------- remove_equalities ---------------------------------------
  116. /* This predicate removes the equality goals from a list of goals. */
  117.  
  118.             % empty list contains no equalities
  119. remove_equalities( [] , [] ) :- !.
  120.  
  121.             % leave out the first subgoal in the input list if it is an
  122.             % equality
  123. remove_equalities( [=(X,X)  | Subgoals],
  124.                    Subgoals_without_equalities ) :-
  125.             % and then make recursive call
  126.                 remove_equalities( Subgoals ,
  127.                                    Subgoals_without_equalities).
  128.  
  129.             % otherwise include the first subgoal in the output,
  130. remove_equalities( [Subgoal | Subgoals],
  131.                    [Subgoal | Subgoals_without_equalities] ) :-
  132.             % and then make recursive call
  133.                 remove_equalities( Subgoals ,
  134.                                    Subgoals_without_equalities).
  135.  
  136.  
  137. %--------------- build_clause --------------------------------------------
  138. /* Given a rule head and a list of subgoals, this predicate builds a
  139.    Prolog clause -- either a fact or rule, as appropriate.
  140. */
  141.          % When there are no subgoals, use the " rule head " as a fact.
  142. build_clause( Head, [], Head) :- !.
  143.  
  144.          % Build a rule for the case where there is just 1 subgoal.
  145. build_clause( Head, [Subgoal], ( Head :- Subgoal ) ) :- !.
  146.  
  147.          % Build a rule with a conjunction of subgoals if there are more
  148.          % than 1 subgoal
  149. build_clause( Head, Subgoals, ( Head :- And_of_Subgoals ) ) :-
  150.              build_conjunction(  Subgoals, And_of_Subgoals).
  151.  
  152.  
  153. %--------------- build_conjunction ---------------------------------------
  154.  
  155.  /*
  156.  Call: build_conjunction( List, Conjunction)
  157.  
  158.  Purpose: convert between a list of goals and a conjunction of goals
  159.  
  160.  Input {Output}  arguments:
  161.  
  162.       List = a list of terms
  163. è Output { Input} arguments
  164.  
  165.       Conjunction = the list of terms ANDed together.
  166.  
  167.  Success conditions:
  168.  
  169.       Succeeds whenever the 2nd arg. can be unified with the conjunction
  170.       of the 1st arg., or the 1st. arg. with the list of goals contained
  171.       in the 2nd. arg. conjunction.
  172.  
  173.  Note:  This predicate works in either direction
  174.  
  175.  Aside for Programmers:  The definition of this predicate is interesting,
  176.        because the recursive rule has to come before the boundary cases.
  177.        Intuitively, this is because the recursive rule is the most
  178.        restrictive, containing 2 somewhat complex patterns.
  179.  
  180.  */
  181.  
  182.  
  183.          % termination case for lists
  184.   build_conjunction( List    ,  Term ) :-
  185.                      not(var(List)),
  186.                      List =  [ Term ],!.
  187.  
  188.          %  AND of no items is always true
  189.   build_conjunction( [], true):-!.
  190.  
  191.          % Here is the recursive rule for conjunctions.
  192.   build_conjunction( [ Term | Terms ], ( Term , And_of_Terms)) :-
  193.                    build_conjunction( Terms , And_of_Terms),!.
  194.  
  195.          % Termination case for conjunctions
  196.   build_conjunction( [ Term ], Term) :-
  197.             not(var( Term)).
  198.  
  199.  
  200. %--------------- test predicate ------------------------------------------
  201.  
  202. test :-
  203.        % nl_log_to_file is an Instant Recall Prolog Tool that saves trace
  204.        % messages to a file -- we have commented out this call, used for
  205.        % debugging only
  206. % nl_log_to_file(log),
  207.   eq_out(
  208.          (prdbms_goal(X) :-
  209.                 book( Authors, Title, Price, Publisher,  Topic, Date),
  210.                 publisher(Name, Address),
  211.                 Publisher = Name,
  212.                 Topic = prolog,
  213.                 X =[ Authors, Title, Publisher, Address ]),
  214.           Out_rule),
  215.     trace_message([$Out_rule = $, Out_rule ])
  216.                                               ,
  217.        % write out results without using trace_messageè    nl, write($Resulting Predicate:$),
  218.     nl, write(Out_rule)
  219.        %
  220.        % closing the log file is also commented out
  221.        %                                        ,
  222.        %       nl_close_log_file
  223.               .
  224.  
  225.  
  226. %---------------- end of eq_out.ari ------------------------------------
  227.  
  228.